package com.step.graphic;

public class TextureRegion {
	Texture texture;
	float u1, v1;
	float u2, v2;
	public TextureRegion () {
	}

	/**
	 *  创建一个纹理区域，大小为整个纹理大小
	 * @param texture
	 */
	public TextureRegion (Texture texture) {
		if (texture == null) throw new IllegalArgumentException("texture cannot be null.");
		this.texture = texture;
		setRegion(0, 0, texture.getWidth(), texture.getHeight());
	}

	/**
	 * 创建纹理区域。其宽度和高度可以为负值，如果高度为负值，则纹理上下颠倒;如果宽度为负值，则纹理左右反转。
	 * @param texture 纹理
	 * @param width 像素宽度
	 * @param height 像素高度
	 */
	public TextureRegion (Texture texture, int width, int height) {
		this.texture = texture;
		setRegion(0, 0, width, height);
	}

	/**
	 * 创建纹理区域。其宽度和高度可以为负值，如果高度为负值，则纹理上下颠倒;如果宽度为负值，则纹理左右反转。
	 * @param texture 纹理
	 * @param x 起点ｘ坐标（纹理中）
	 * @param y 起点ｙ坐标（纹理中）
	 * @param width 像素宽度
	 * @param height 像素高度
	 */
	public TextureRegion (Texture texture, int x, int y, int width, int height) {
		this.texture = texture;
		setRegion(x, y, width, height);
	}

	/**
	 * 创建纹理区域
	 * @param texture 纹理
	 * @param u1 起点u坐标
	 * @param v1 起点v坐标
	 * @param u2 终点u坐标
	 * @param v2 终点v坐标
	 */
	public TextureRegion (Texture texture, float u1, float v1, float u2, float v2) {
		this.texture = texture;
		setRegion(u1, v1, u2, v2);
	}

	/**
	 * 创建纹理区域，该区域与给定纹理区域相同大小。
	 * @param region 纹理区域
	 */
	public TextureRegion (TextureRegion region) {
		setRegion(region);
	}

	/**
	 * 创建纹理区域，其宽度和高度可以为负值，如果高度为负值，则纹理上下颠倒;如果宽度为负值，则纹理左右反转。
	 * @param region 纹理区域
	 * @param x 起点ｘ坐标（纹理区域中）
	 * @param y 起点 ｙ坐标（纹理区域中）
	 * @param width 像素宽度
	 * @param height 像素高度
	 */
	public TextureRegion (TextureRegion region, int x, int y, int width, int height) {
		setRegion(region, x, y, width, height);
	}
	
	/**
	 * 设定纹理区域
	 * @param texture
	 */
	public void setRegion (Texture texture) {
		this.texture = texture;
		setRegion(0, 0, texture.getWidth(), texture.getHeight());
	}

	/**
	 * 设定纹理区域
	 * @param x 起点ｘ坐标
	 * @param y 起点ｙ坐标
	 * @param width 像素宽度
	 * @param height 像素高度
	 */
	public void setRegion (int x, int y, int width, int height) {
		float invTexWidth = 1f / texture.getWidth();
		float invTexHeight = 1f / texture.getHeight();
		setRegion(x * invTexWidth, y * invTexHeight, (x + width) * invTexWidth, (y + height) * invTexHeight);
	}

	/**
	 * 设定纹理区域
	 * @param u1 起点u坐标
	 * @param v1 起点v坐标
	 * @param u2 终点u坐标
	 * @param v2 终点v坐标
	 */
	public void setRegion (float u1, float v1, float u2, float v2) {
		this.u1 = u1;
		this.v1 = v1;
		this.u2 = u2;
		this.v2 = v2;
	}

	/**
	 * 设定纹理区域
	 * @param region 纹理区域
	 */
	public void setRegion (TextureRegion region) {
		texture = region.texture;
		setRegion(region.u1, region.v1, region.u2, region.v2);
	}

	/**
	 * 设定纹理区域
	 * @param region 纹理区域
	 * @param x 起点ｘ坐标
	 * @param y 起点ｙ坐标
	 * @param width 像素宽度
	 * @param height 像素高度
	 */
	public void setRegion (TextureRegion region, int x, int y, int width, int height) {
		texture = region.texture;
		setRegion(region.getRegionX() + x, region.getRegionY() + y, width, height);
	}

	public Texture getTexture () {
		return texture;
	}

	public void setTexture (Texture texture) {
		this.texture = texture;
	}

	public float getU1 () {
		return u1;
	}

	public void setU1 (float u1) {
		this.u1 = u1;
	}

	public float getV1 () {
		return v1;
	}

	public void setV1 (float v1) {
		this.v1 = v1;
	}

	public float getU2 () {
		return u2;
	}

	public void setU2 (float u2) {
		this.u2 = u2;
	}

	public float getV2 () {
		return v2;
	}

	public void setV2 (float v2) {
		this.v2 = v2;
	}

	public int getRegionX () {
		return (int)(u1 * texture.getWidth());
	}

	public void setRegionX (int x) {
		setU1(x / (float)texture.getWidth());
	}

	public int getRegionY () {
		return (int)(v1 * texture.getHeight());
	}

	public void setRegionY (int y) {
		setV1(y / (float)texture.getHeight());
	}

	/**
	 * 返回区域宽度，如果为负值，水平反转
	 * @return
	 */
	public int getRegionWidth () {
		return Math.round((u2 - u1) * texture.getWidth());
	}

	public void setRegionWidth (int width) {
		setU2(u1 + width / (float)texture.getWidth());
	}

	/**
	 * 返回区域高度，如果为负值，垂直反转
	 * @return
	 */
	public int getRegionHeight () {
		return Math.round((v2 - v1) * texture.getHeight());
	}

	public void setRegionHeight (int height) {
		setV2(v1 + height / (float)texture.getHeight());
	}

	public void flip (boolean x, boolean y) {
		if (x) {
			float temp = u1;
			u1 = u2;
			u2 = temp;
		}
		if (y) {
			float temp = v1;
			v1 = v2;
			v2 = temp;
		}
	}

	/**
	 * 纹理区域相对于当前区域偏移。通常纹理区域的大小为整个纹理大小。
	 * @param offsetX ｘ方向偏移量
	 * @param offsetY ｙ方向偏移量
	 */
	public void scroll (float offsetX, float offsetY) {
		if (offsetX != 0) {
			float width = (u2 - u1) * texture.getWidth();
			u1 = (u1 + offsetX) % 1;
			u2 = u1 + width / texture.getWidth();
		}
		if (offsetY != 0) {
			float height = (v2 - v1) * texture.getHeight();
			v1 = (v1 + offsetY) % 1;
			v2 = v1 + height / texture.getHeight();
		}
	}

	/**
	 * 将纹理区域按给定的宽度和高度切片。从左上角开始向右向下切分，直到右下角。如果最后一个片的大小不是给定的宽度和高度，则丢弃。
	 * @param tileWidth 切片宽度
	 * @param tileHeight 切片高度
	 * @return
	 */
	public TextureRegion[][] split (int tileWidth, int tileHeight) {
		int x = getRegionX();
		int y = getRegionY();
		int width = getRegionWidth();
		int height = getRegionHeight();

		if (width < 0) {
			x = x - width;
			width = -width;
		}

		if (height < 0) {
			y = y - height;
			height = -height;
		}

		int rows = height / tileHeight;
		int cols = width / tileWidth;

		int startX = x;
		TextureRegion[][] tiles = new TextureRegion[rows][cols];
		for (int row = 0; row < rows; row++, y += tileHeight) {
			x = startX;
			for (int col = 0; col < cols; col++, x += tileWidth) {
				tiles[row][col] = new TextureRegion(texture, x, y, tileWidth, tileHeight);
			}
		}

		return tiles;
	}
	
	public TextureRegion[] splitToRegions (int tileWidth, int tileHeight) {
		int x = getRegionX();
		int y = getRegionY();
		int width = getRegionWidth();
		int height = getRegionHeight();

		if (width < 0) {
			x = x - width;
			width = -width;
		}

		if (height < 0) {
			y = y - height;
			height = -height;
		}

		int rows = height / tileHeight;
		int cols = width / tileWidth;

		int startX = x;
		TextureRegion[] tiles = new TextureRegion[rows * cols];
		int index = 0;
		for (int row = 0; row < rows; row++, y += tileHeight) {
			x = startX;
			for (int col = 0; col < cols; col++, x += tileWidth) {
				tiles[index++] = new TextureRegion(texture, x, y, tileWidth, tileHeight);
			}
		}

		return tiles;
	}

	/**
	 * 将纹理区域按给定的宽度和高度切片。从左上角开始向右向下切分，直到右下角。如果最后一个片的大小不是给定的宽度和高度，则丢弃。
	 * @param texture 纹理
	 * @param tileWidth 切片宽度
	 * @param tileHeight 切片高度
	 * @return
	 */
	public static TextureRegion[][] split (Texture texture, int tileWidth, int tileHeight) {
		TextureRegion region = new TextureRegion(texture);
		return region.split(tileWidth, tileHeight);
	}
	
	public static TextureRegion[] splitToRegions (Texture texture, int tileWidth, int tileHeight) {
		TextureRegion region = new TextureRegion(texture);
		return region.splitToRegions(tileWidth, tileHeight);
	}
}
